﻿#ifndef SPECTRUM_H
#define SPECTRUM_H

#include "fftw3.h"
#include <string>

#define R2FFT 0 //实转fft
#define C2FFT 1 //复转fft

#define WIN_None 0            //不加窗（暂时默认一半）
#define WIN_Rectangle 1       //矩形窗
#define WIN_Bartlett 2        //三角形窗
#define WIN_Hanning 3         //汉宁窗
#define WIN_Hamming 4         //海明窗
#define WIN_Blackman 5        //布莱克曼窗
#define WIN_BlackmanHarris 6  //布莱克曼-哈里斯窗
#define WIN_BlackmanNuttall 7 //布莱克曼-纳托儿窗
#define WIN_Nuttall 8         //纳托儿窗
#define WIN_Gaussian 9        //高斯窗
#define WIN_FlatTop 10        //平顶窗
#define WIN_KaiserBasel 11    //凯赛-贝塞尔窗 (未实现)
#define WIN_Chebyshev 12      //切比雪夫窗 (未实现)

class Spectrum
{
public:
    /**
     * @brief Spectrum  初始化fft变换类
     * @param outFftLen 输出fft长度 这里设置的长度对应（输入样点数要是他的2倍）
     * @param winType   窗体类型
     * @param type      处理模式（默认实信号输入）
     */
    explicit Spectrum(int outFftLen, int winType, int type = R2FFT);
    void setWinType(int winType);
    void getWindow(short value, short outBuf[]);
    ~Spectrum();

    /**
     * @brief ConversionMAX FFT变换
     * @param inBuf     输入数组
     * @param inLen      输入长度
     * @param outBuf    输出数据
     * @param levelPoor 电平差 | 计算方法：先用0差，计算出来的fft电平值与信号源上电平值求差  | 内部计算为 fft+levelPoor
     * @param smooth    平滑（默认不平滑）
     * @param smoothNum 平滑次数 （默认8）
     */
    void ConversionMAX(short inBuf[], int inLen, float outBuf[], float levelPoor = 0, bool smooth = false, int smoothNum = 8);

    void ConversionMEAN(short inBuf[], int inLen, float outBuf[], float levelPoor = 0, bool smooth = false, int smoothNum = 8);

    void ConversionMIN(short inBuf[], int inLen, float outBuf[], float levelPoor = 0, bool smooth = false, int smoothNum = 8);
    /**
     * @brief Conversion FFT变换 输入short输出short
     * @param inBuf     输入数组
     * @param inLen      输入长度
     * @param outBuf    输出数据
     * @param levelPoor 电平差 | 计算方法：先用0差，计算出来的fft电平值与信号源上电平值求差  | 内部计算为 fft+levelPoor
     * @param smooth    平滑（默认不平滑）
     * @param smoothNum 平滑次数 （默认8）
     */
    void ConversionMAX(short inBuf[], int inLen, short outBuf[], short levelPoor = 0, bool smooth = false, int smoothNum = 8);

    void ConversionMEAN(short inBuf[], int inLen, short outBuf[], short levelPoor = 0, bool smooth = false, int smoothNum = 8);

    void ConversionMIN(short inBuf[], int inLen, short outBuf[], short levelPoor = 0, bool smooth = false, int smoothNum = 8);

    /**
     * @brief Conversion FFT变换 输入float 输出 short
     * @param inBuf     输入数组
     * @param inLen      输入长度
     * @param outBuf    输出数据
     * @param levelPoor 电平差 | 计算方法：先用0差，计算出来的fft电平值与信号源上电平值求差  | 内部计算为 fft+levelPoor
     * @param smooth    平滑（默认不平滑）
     * @param smoothNum 平滑次数 （默认8）
     */
    void ConversionMAX(float inBuf[], int inLen, short outBuf[], short levelPoor = 0, bool smooth = false, int smoothNum = 8);

    /**
     * @brief Conversion FFT变换 输入float 输出 float
     * @param inBuf     输入数组
     * @param inLen      输入长度
     * @param outBuf    输出数据
     * @param levelPoor 电平差 | 计算方法：先用0差，计算出来的fft电平值与信号源上电平值求差  | 内部计算为 fft+levelPoor
     * @param smooth    平滑（默认不平滑）
     * @param smoothNum 平滑次数 （默认8）
     */
    void ConversionMAX(float inBuf[], int inLen, float outBuf[], short levelPoor = 0, bool smooth = false, int smoothNum = 8);

private:
    //参数区/////////////////////////////////
    int disposeType; //处理方式
    int workLen;     //都是fft长度的2倍
    int fftLen;      //fft长度

    int winType;   //滤波窗类型
    float *winBuf; //滤波窗

    fftwf_plan real_plan;
    float *rInBuf;
    float *rOutBuf;
    fftwf_complex *cInBuf;
    fftwf_complex *cOutBuf;

    float *fOutBuf; //输出short时用来临时存储float用
};

#endif // SPECTRUM_H
